#include <stdio.h>     // 标准输入输出函数
#include <stdlib.h>    // 内存分配、进程控制函数
#include <string.h>    // 字符串操作函数
#include <unistd.h>    // UNIX标准函数（如sleep）
#include <arpa/inet.h> // 网络通信函数（如inet_pton）
#include <pthread.h>   // 多线程支持
#include <errno.h>     // 错误码定义
#include <sys/time.h>  // 时间相关函数（如setsockopt超时设置）

// 定义定时发送的数据包（模拟某种协议格式）
const char *bg_message = "BG,..,..,..,..,ED\n";

// 服务器配置结构体
typedef struct {
    const char *ip;    // 服务器IP地址
    int port;          // 服务器端口号
    const char *name;  // 服务器标识名（用于日志）
} ServerConfig;

// 双服务器配置
ServerConfig servers[2] = {
    {"8.135.10.183", 31942, "Server1"},  // 第一个服务器配置
    {"112.125.89.8", 43348, "Server2"}   // 第二个服务器配置
};

// 常量定义
#define BUFFER_SIZE 1024                 // 接收缓冲区大小
#define HEARTBEAT_INTERVAL 60            // 心跳间隔（未使用）
#define RECONNECT_BASE_DELAY 1           // 重连基础延迟（秒）
#define MAX_RECONNECT_ATTEMPTS 5         // 最大重试次数

// 连接状态结构体
typedef struct {
    int sock;                  // 套接字描述符
    int is_connected;          // 是否已连接
    int reconnect_attempts;    // 当前重试次数
    time_t last_activity;      // 最后活动时间（用于检测连接状态）
    time_t last_bg_send;       // 上次发送BG消息时间
    pthread_mutex_t lock;      // 互斥锁（保护共享资源）
    pthread_cond_t cond;       // 条件变量（用于线程同步）
    ServerConfig config;       // 服务器配置信息
} ConnectionState;

// 初始化连接状态
void connection_init(ConnectionState *conn, ServerConfig config) {
    conn->sock = -1;                   // 初始套接字无效
    conn->is_connected = 0;            // 初始未连接
    conn->reconnect_attempts = 0;      // 重试次数清零
    conn->last_activity = 0;           // 最后活动时间清零
    conn->last_bg_send = 0;            // 最后发送时间清零
    conn->config = config;             // 保存服务器配置
    pthread_mutex_init(&conn->lock, NULL);       // 初始化互斥锁
    pthread_cond_init(&conn->cond, NULL);        // 初始化条件变量
}

// 创建socket（带配置参数）
int create_socket(ServerConfig config) {
    int sock = socket(AF_INET, SOCK_STREAM, 0);  // 创建TCP套接字
    if (sock < 0) {
        perror("Socket creation failed");        // 错误处理
        return -1;
    }

    // 设置发送超时时间为5秒
    struct timeval tv_send = {.tv_sec = 5, .tv_usec = 0};
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv_send, sizeof(tv_send));
    
    printf("[%s] Socket created\n", config.name);  // 打印调试信息
    return sock;
}

// 连接到指定服务器
int connect_to_server(int sock, ServerConfig config) {
    struct sockaddr_in server_addr = {
        .sin_family = AF_INET,                    // IPv4协议
        .sin_port = htons(config.port)            // 端口号转为网络字节序
    };

    // 将IP地址字符串转换为网络地址
    if (inet_pton(AF_INET, config.ip, &server_addr.sin_addr) <= 0) {
        perror("Invalid address");               // 错误处理
        return -1;
    }

    // 设置连接超时时间为5秒
    struct timeval tv_connect = {.tv_sec = 5, .tv_usec = 0};
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv_connect, sizeof(tv_connect));
    
    printf("[%s] Connecting to %s:%d...\n", config.name, config.ip, config.port);  // 打印调试信息
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {  // 发起连接
        perror("Connection failed");                                              // 错误处理
        return -1;
    }
    return 0;
}

// 接收线程函数（带服务器标识）
void* receiver_thread(void* arg) {
    ConnectionState *conn = (ConnectionState*)arg;  // 获取连接状态
    char buffer[BUFFER_SIZE];                       // 接收缓冲区

    while (1) {
        pthread_mutex_lock(&conn->lock);            // 加锁保护共享资源
        
        while (!conn->is_connected) {               // 如果未连接，等待条件变量
            pthread_cond_wait(&conn->cond, &conn->lock);
        }

        // 设置接收超时时间为1秒
        struct timeval tv = {.tv_sec = 1, .tv_usec = 0};
        setsockopt(conn->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

        ssize_t valread = recv(conn->sock, buffer, BUFFER_SIZE, 0);  // 接收数据
        if (valread > 0) {
            buffer[valread] = '\0';                                  // 添加字符串结束符
            printf("[%s] Received %zd bytes: %s\n", 
                  conn->config.name, valread, buffer);               // 打印接收到的数据
            conn->last_activity = time(NULL);                        // 更新最后活动时间
        } else if (valread == 0) {
            printf("[%s] Connection closed by server\n", conn->config.name);  // 服务器主动关闭
            close(conn->sock);                                           // 关闭套接字
            conn->is_connected = 0;                                      // 标记为未连接
            pthread_cond_signal(&conn->cond);                            // 通知发送线程重连
        } else {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {              // 非超时错误
                printf("[%s] Receive error: %s\n", 
                      conn->config.name, strerror(errno));              // 打印错误信息
                close(conn->sock);                                       // 关闭套接字
                conn->is_connected = 0;                                  // 标记为未连接
                pthread_cond_signal(&conn->cond);                        // 通知发送线程重连
            }
        }

        pthread_mutex_unlock(&conn->lock);            // 释放锁
        sleep(1);                                     // 休眠防止CPU过载
    }
    return NULL;
}

// 发送线程函数（带服务器标识）
void* sender_thread(void* arg) {
    ConnectionState *conn = (ConnectionState*)arg;  // 获取连接状态

    while (1) {
        pthread_mutex_lock(&conn->lock);            // 加锁保护共享资源

        if (!conn->is_connected) {                  // 如果未连接
            int delay = RECONNECT_BASE_DELAY << conn->reconnect_attempts;  // 计算重试延迟
            printf("[%s] Reconnecting in %ds...\n", 
                  conn->config.name, delay);
            
            pthread_mutex_unlock(&conn->lock);      // 释放锁进行重连
            sleep(delay);                           // 休眠等待
            pthread_mutex_lock(&conn->lock);        // 重新加锁

            // 尝试创建套接字并连接
            if ((conn->sock = create_socket(conn->config)) == -1 ||
                connect_to_server(conn->sock, conn->config) == -1) {
                close(conn->sock);                 // 关闭套接字
                conn->sock = -1;                   // 标记为无效
                if (conn->reconnect_attempts < MAX_RECONNECT_ATTEMPTS) {
                    conn->reconnect_attempts++;    // 增加重试次数
                }
                pthread_mutex_unlock(&conn->lock); // 释放锁继续循环
                continue;
            }

            printf("[%s] Connected successfully\n", conn->config.name);  // 打印成功信息
            conn->is_connected = 1;                                      // 标记为已连接
            conn->reconnect_attempts = 0;                                // 重置重试次数
            conn->last_activity = time(NULL);                            // 更新最后活动时间
            pthread_cond_signal(&conn->cond);                            // 通知接收线程
        }

        // 每28秒发送一次BG消息
        time_t now = time(NULL);
        if (now - conn->last_bg_send >= 28) {
            ssize_t sent = send(conn->sock, bg_message, strlen(bg_message), 0);  // 发送数据
            if (sent < 0) {
                printf("[%s] BG send failed: %s\n", 
                      conn->config.name, strerror(errno));  // 打印错误信息
                close(conn->sock);                          // 关闭套接字
                conn->is_connected = 0;                     // 标记为未连接
            } else {
                printf("[%s] Sent BG message (%zd bytes)\n", 
                      conn->config.name, sent);             // 打印发送成功信息
                conn->last_bg_send = now;                   // 更新最后发送时间
                conn->last_activity = now;                  // 更新最后活动时间
            }
        }

        pthread_mutex_unlock(&conn->lock);  // 释放锁
        sleep(1);                           // 休眠防止CPU过载
    }
    return NULL;
}

int main() {
    // 初始化两个连接
    ConnectionState conn[2];
    for(int i=0; i<2; i++){
        connection_init(&conn[i], servers[i]);  // 初始化每个连接的状态
    }

    // 创建4个线程（每个连接2个线程：发送+接收）
    pthread_t tid[4];
    
    for(int i=0; i<2; i++){
        if(pthread_create(&tid[i*2], NULL, sender_thread, &conn[i])) {
            perror("Thread create failed");     // 错误处理
            exit(EXIT_FAILURE);
        }
        if(pthread_create(&tid[i*2+1], NULL, receiver_thread, &conn[i])) {
            perror("Thread create failed");     // 错误处理
            exit(EXIT_FAILURE);
        }
    }

    // 监控线程（每10秒打印一次状态）
    while(1) {
        sleep(10);
        for(int i=0; i<2; i++){
            pthread_mutex_lock(&conn[i].lock);
            printf("[%s] Status: %s, Socket: %d\n",
                  conn[i].config.name,
                  conn[i].is_connected ? "Connected" : "Disconnected",
                  conn[i].sock);
            pthread_mutex_unlock(&conn[i].lock);
        }
    }

    // 清理资源（理论上不会执行到这里）
    for(int i=0; i<2; i++){
        pthread_join(tid[i*2], NULL);
        pthread_join(tid[i*2+1], NULL);
        pthread_mutex_destroy(&conn[i].lock);
        pthread_cond_destroy(&conn[i].cond);
    }
    
    return 0;
}
